using System;
using System.Collections.Generic;
using System.Text;

namespace WOWEquipOptimizer.Mage
{
    class Fire : CasterDD
    {
        public Fire()
            : base()
        {
            m_Base = new List<Attribute>();
            m_Base.Add(new Attribute(AttributeName.Health, 3200));
            m_Base.Add(new Attribute(AttributeName.Stamina, 52));
            m_Base.Add(new Attribute(AttributeName.Mana, 2000));
            m_Base.Add(new Attribute(AttributeName.Intellect, 149));
            m_Base.Add(new Attribute(AttributeName.Spirit, 150));
            m_Base.Add(new Attribute(AttributeName.CritSpellRating, 0.9f * CritSpellRating));
            // talents
            m_Base.Add(new Attribute(AttributeName.HitSpellRating, 3 * HitSpellRating));
            m_Base.Add(new Attribute(AttributeName.CritSpellRating, (3 + 6 + 3) * CritSpellRating));
            foreach (Attribute attr in m_Base)
            {
                handleAttribute(attr);
            }
            /*
             * Above is the proper way to do it, since this actually covers all the buffs properly
             */
        }
        // mana, int, spirit, spelldmg, spellcrit, spellhit, spellhaste,mp5,health
        // simplified 5 scorch, 7 fb
        public override float evaluateTF()
        {
            float runtime = 600;
            float time = runtime;
            float mana = m_Equip[AttributeName.Mana];
            float intellect = m_Equip[AttributeName.Intellect];
            float spirit = m_Equip[AttributeName.Spirit];
            float spelldmg = m_Equip[AttributeName.SpellDamage];
            float crit = m_Equip[AttributeName.CritSpellRating] / CritSpellRating;
            float hit = m_Equip[AttributeName.HitSpellRating] / HitSpellRating;
            hit = Math.Min(83f + hit, 99);
            float haste = m_Equip[AttributeName.HasteSpellRating] / HasteSpellRating;
            float mp5 = m_Equip[AttributeName.MP5];
            float rottime = 30;
            float scorchcount = 5 / (hit / 100f);
            float fbcount = ((rottime - scorchcount * 1.75f) / (3 / (1 + haste / 100f))) * (hit / 100f);
            if (this.SpecialValues.Contains("27253988"))
            {
                float castcount = (scorchcount + fbcount) / 3f;
                float notproc = (float) Math.Pow(hit/100f, castcount);
                spelldmg += (1 - notproc) * 170f;
            }
            float scorchdmg = (333 + (1.5f / 3.5f) * spelldmg);
            float scorchmana = 0.97f * 0.97f * (180 * (1 - ((crit + 4) / 100) * 0.3f));
            float scorchcritmult = 1 + 1.1f * 0.5f * (crit / 100f);
            float fbdmg = 1.035f * spelldmg + 803f;
            float fbmana = 0.97f * 0.97f * (425 * (1 - (crit / 100) * 0.3f));
            float fbcritmult = 1 + 1.1f * 0.5f * ((crit + 4) / 100f);
            float evocation = ((spirit / 4f + 12.5f) * 16f * 4f) * (runtime / (8 * 60));
            float rotdmg = 1.1f * 1.03f * (5.3f * scorchcritmult * scorchdmg + fbcount * fbcritmult * 1.15f * fbdmg);
            float rotmana = Math.Max(0.9f * (scorchcount * scorchmana + fbcount * fbmana) - mp5 * 6 - evocation / (runtime / rottime), 1);
            float rotcount = Math.Min(mana / rotmana, runtime / rottime);
            float manapersec = rotmana / rottime;
            float manaregooc = ((spirit / 4f + 12.5f) * 2.5f + mp5)/5;
            float castuseratio = manaregooc / manapersec;
            time -= (rotcount * rottime) + Math.Max(5 * castuseratio, 5);
            time = Math.Max(time, 0);
            float regtime = 0;
            if (time > 0)
            {
                regtime = time / (castuseratio + 1);
                time -= regtime;
            }
            rotcount += Math.Min((regtime * manaregooc) / rotmana, time / rottime);
            float finaldps = (rotdmg * rotcount) / runtime;
            return CondFactor * finaldps;
        }

        // mana, int, spirit, spelldmg, spellcrit, spellhit, spellhaste, mp5,health
        public override void handleAttribute(Attribute attr)
        {
            switch (attr.Type)
            {
                case AttributeName.Intellect:
                    m_Equip[AttributeName.Mana] += attr.Value * (HasBlessingOfKings ? 1.1f : 1.0f) * 15;
                    m_Equip[AttributeName.Intellect] += attr.Value * (HasBlessingOfKings ? 1.1f : 1.0f);
                    m_Equip[AttributeName.CritSpellRating] += (attr.Value * (HasBlessingOfKings ? 1.1f : 1.0f) / 80) * CritSpellRating;
                    break;
                case AttributeName.FireSpellDamage:
                case AttributeName.SpellDamage:
                    m_Equip[AttributeName.SpellDamage] += attr.Value;
                    break;
                default:
                    base.handleAttribute(attr);
                    break;
            }
        }
        public override List<Item> filterEquip(List<Item> input)
        {
            input = base.filterEquip(input);
            List<Item> retval = new List<Item>();
            ItemBlacklist.Add("Atiesh, Greatstaff of the Guardian");
            ItemBlacklist.Add("Violet Signet");
            foreach (Item item in input)
            {
                if ((item.AllowableClasses & CharacterClass.Mage) == 0) continue;
                if (item.GetType() == typeof(Weapon))
                {
                    Weapon weapon = (Weapon)item;
                    if (weapon.WeaponSlot == WeaponSlot.Ranged)
                    {
                        if (weapon.Type != WeaponType.Wand) continue;
                    }
                    if (weapon.Type == WeaponType.Axe || weapon.Type == WeaponType.Mace) continue;
                    if (weapon.TwoHand && weapon.Type != WeaponType.Staff) continue;
                }
                else if (item.GetType() == typeof(Armor))
                {
                    Armor armor = (Armor)item;
                    if ((armor.Type & ArmorProficiency.Cloth) == 0) continue;
                }
                if (SetBlacklist.Contains(item.Set.Name)) continue;
                if (ItemBlacklist.Contains(item.Name)) continue;
                retval.Add(item);
            }
            return handleWhiteList(retval);
        }
        public override bool evaluateBuild(int[] build)
        {
            if (build[1] >= 41 && build[0] >= 10 && build[2] >= 3)
            {
                return true;
            }
            else return false;
        }
    }
}
